import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('可拖拽小圆点')),
        body: const Center(child: DotDragExample()),
      ),
    );
  }
}

class DotDragExample extends StatefulWidget {
  const DotDragExample({super.key});
  @override
  State<DotDragExample> createState() => _DotDragExampleState();
}

class _DotDragExampleState extends State<DotDragExample> {
  // 初始位置（相对于父容器左上角）
  Offset _dotPos = const Offset(60, 60);

  // 小圆点半径
  final double _radius = 12;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 300,
      height: 400,
      child: LayoutBuilder(
        builder: (context, constraints) {
          final double maxW = constraints.maxWidth;
          final double maxH = constraints.maxHeight;

          // 确保初始位置在边界内
          _dotPos = Offset(_dotPos.dx.clamp(_radius, maxW - _radius), _dotPos.dy.clamp(_radius, maxH - _radius));

          return Stack(
            children: [
              // 背景区域（可选：显示边框帮助观察）
              Container(
                decoration: BoxDecoration(
                  color: Colors.grey.shade100,
                  border: Border.all(color: Colors.grey),
                ),
              ),

              // 可拖拽的小圆点（使用 Positioned 根据中心点放置）
              Positioned(
                left: _dotPos.dx - _radius, // 因为我们用的是中心点，所以 left = x - r
                top: _dotPos.dy - _radius,
                child: GestureDetector(
                  behavior: HitTestBehavior.translucent,
                  onPanUpdate: (details) {
                    setState(() {
                      // 使用 delta 更新位置，并做边界限制
                      double newX = (_dotPos.dx + details.delta.dx).clamp(_radius, maxW - _radius);
                      double newY = (_dotPos.dy + details.delta.dy).clamp(_radius, maxH - _radius);
                      _dotPos = Offset(newX, newY);
                    });
                  },
                  onPanStart: (_) {
                    // 可用于触摸开始时的效果（比如放大、变色）
                  },
                  onPanEnd: (_) {
                    // 可用于触摸结束时的效果
                  },
                  child: Container(
                    width: _radius * 2,
                    height: _radius * 2,
                    decoration: BoxDecoration(
                      color: Colors.blue,
                      shape: BoxShape.circle,
                      boxShadow: [
                        BoxShadow(color: Colors.black.withOpacity(0.2), blurRadius: 4, offset: const Offset(0, 2)),
                      ],
                    ),
                  ),
                ),
              ),

              // 可选：显示坐标文本，便于调试
              Positioned(
                left: 8,
                bottom: 8,
                child: Container(
                  padding: const EdgeInsets.all(6),
                  color: Colors.white.withOpacity(0.8),
                  child: Text('x: ${_dotPos.dx.toStringAsFixed(1)}, y: ${_dotPos.dy.toStringAsFixed(1)}'),
                ),
              ),
            ],
          );
        },
      ),
    );
  }
}
